sap restful json接口动态调用RFC,生成动态结构

您所在的位置:网站首页 json 接口 sap restful json接口动态调用RFC,生成动态结构

sap restful json接口动态调用RFC,生成动态结构

#sap restful json接口动态调用RFC,生成动态结构| 来源: 网络整理| 查看: 265

需求:项目上有一个restful接口需求,想着能不能做成动态的,只发布一个sap的restful接口出去,然后外围系统根据不同的json来动态调用sap的rfc。

结果:结合同事以前的开发demo和abapgit上面大佬的abap_fm_json demo,写了一个简易的demo,如下代码: 在这里插入图片描述

METHOD http_broker. DATA: ptab TYPE abap_func_parmbind_tab, ptab_line TYPE abap_func_parmbind, etab TYPE abap_func_excpbind_tab, etab_line TYPE abap_func_excpbind, data_export TYPE REF TO data, data_ref TYPE REF TO data, lv_response_json TYPE string. "接口返回参数 DATA: dyn_table TYPE REF TO data. DATA: lt_dd04l TYPE STANDARD TABLE OF dd04l. DATA:lv_error_msg TYPE bapi_msg. "检查函数是否存在 SELECT funcname, paramtype, pposition, parameter, structure FROM fupararef WHERE funcname = @iv_function_name INTO TABLE @DATA(parameters_tab). IF sy-subrc 0. response->set_status( code = 400 reason = 'target_function no exist,Please check the url address' ). EXIT. ENDIF. LOOP AT parameters_tab ASSIGNING FIELD-SYMBOL(). IF strlen( -structure ) > 30. CONTINUE. ENDIF. lt_dd04l = VALUE #( BASE lt_dd04l ( domname = -structure ) ). ENDLOOP. IF lt_dd04l IS NOT INITIAL. SELECT domname FROM dd04l FOR ALL ENTRIES IN @lt_dd04l WHERE domname = @lt_dd04l-domname INTO TABLE @DATA(data_elements). ENDIF. " MAPPING 字段映射 me->json_mapping( EXPORTING iv_function_name = iv_function_name IMPORTING name_mappings_i = DATA(lt_mapping_i) name_mappings_o = DATA(lt_mapping_o) name_mappings_x = DATA(lt_mapping_x) ). TRY. "函数入参动态拼接 LOOP AT parameters_tab ASSIGNING FIELD-SYMBOL(). CLEAR ptab_line. ptab_line-name = -parameter. ptab_line-kind = COND #( WHEN -paramtype = 'E' THEN abap_func_importing WHEN -paramtype = 'I' THEN abap_func_exporting WHEN -paramtype = 'T' THEN abap_func_tables WHEN -paramtype = 'C' THEN abap_func_changing ELSE '' ). DATA(json_field_name) = COND string( WHEN ptab_line-kind = abap_func_exporting THEN 'IMPORT' WHEN ptab_line-kind = abap_func_tables THEN 'TABLE' WHEN ptab_line-kind = abap_func_changing THEN 'CHANGE' WHEN ptab_line-kind = abap_func_importing THEN 'EXPORT' ELSE '' ). "解析传入参数 DATA(json) = request->get_cdata( ). DATA(json_data) = zcl_json=>generate( json = json name_mappings = lt_mapping_i ). ASSIGN json_data->* TO FIELD-SYMBOL(). READ TABLE lt_mapping_x INTO DATA(ls_x) WITH KEY abap = -parameter. IF sy-subrc EQ 0. DATA(lv_parameter) = ls_x-json. ELSE. lv_parameter = -parameter. ENDIF. "根据函数的入参匹配接口传入参数 ASSIGN COMPONENT lv_parameter OF STRUCTURE TO FIELD-SYMBOL(). IF sy-subrc 0 OR json_field_name = 'EXPORT'. CASE json_field_name. WHEN 'TABLE'. "创建动态表结构 CREATE DATA dyn_table TYPE TABLE OF (-structure). "创建动态内表 ASSIGN dyn_table->* TO FIELD-SYMBOL(). GET REFERENCE OF INTO ptab_line-value. INSERT ptab_line INTO TABLE ptab. CONTINUE. WHEN OTHERS. "动态定义承接返回参数的结构 CREATE DATA data_export TYPE (-structure). ASSIGN data_export TO FIELD-SYMBOL(). ptab_line-value = . INSERT ptab_line INTO TABLE ptab. CONTINUE. ENDCASE. ENDIF. CREATE DATA data_ref TYPE (-structure). FIELD-SYMBOLS: TYPE any. ASSIGN ->* TO . IF data_ref IS BOUND. ASSIGN data_ref->* TO FIELD-SYMBOL(). ENDIF. "将传入参数按照特定格式转换 IF line_exists( data_elements[ domname = -structure ] ). = . ELSE. DATA(json_temp) = /ui2/cl_json=>serialize( data = ). /ui2/cl_json=>deserialize( EXPORTING json = json_temp name_mappings = lt_mapping_i CHANGING data = ). ENDIF. GET REFERENCE OF INTO ptab_line-value. INSERT ptab_line INTO TABLE ptab. ENDLOOP. CATCH cx_sy_create_data_error INTO DATA(lo_data_error). lv_error_msg = lo_data_error->get_text( ). me->set_message( EXPORTING request = request iv_function_name = iv_function_name iv_code = 400 iv_mtype = 'E' iv_reason = 'target_function Handling Exceptions' iv_message = lv_error_msg IMPORTING response = response ). EXIT. ENDTRY. etab_line-name = 'OTHERS'. etab_line-value = 10. INSERT etab_line INTO TABLE etab. TRY. "动态调用函数,业务逻辑部分 CALL FUNCTION iv_function_name PARAMETER-TABLE ptab EXCEPTION-TABLE etab. SORT parameters_tab BY parameter. CLEAR:data_ref. UNASSIGN:. LOOP AT ptab INTO ptab_line WHERE kind abap_func_exporting. ASSIGN ptab_line-value->* TO . "Serialize Data to Json DATA(lv_string) = /ui2/cl_json=>serialize( data = name_mappings = lt_mapping_o ). READ TABLE lt_mapping_x INTO ls_x WITH KEY abap = ptab_line-name. IF sy-subrc EQ 0. lv_parameter = ls_x-json. ELSE. lv_parameter = ptab_line-name. ENDIF. IF lv_response_json IS INITIAL. lv_response_json = |"{ lv_parameter }":{ lv_string }|. ELSE. lv_response_json = |{ lv_response_json },"{ lv_parameter }":{ lv_string }|. ENDIF. ENDLOOP. lv_response_json = '{' && lv_response_json && '}'. CATCH cx_sy_dyn_call_param_not_found INTO DATA(lo_error_no_found). lv_error_msg = lo_error_no_found->get_text( ). CATCH cx_sy_dyn_call_param_missing INTO DATA(lo_error_missing). lv_error_msg = lo_error_missing->get_text( ). CATCH cx_sy_dyn_call_parameter_error INTO DATA(lo_error_parameter). lv_error_msg = lo_error_parameter->get_text( ). CATCH cx_sy_dyn_call_error INTO DATA(lo_error_call). lv_error_msg = lo_error_call->get_text( ). ENDTRY. IF lv_error_msg IS NOT INITIAL. me->set_message( EXPORTING request = request iv_function_name = iv_function_name iv_code = 400 iv_mtype = 'E' iv_reason = 'target_function Handling Exceptions' iv_message = lv_error_msg IMPORTING response = response ). EXIT. ENDIF. response->set_status( code = 200 reason = '' ). response->set_header_field( name = 'Content-Type' value = 'application/json' ). response->set_cdata( lv_response_json ). ENDMETHOD.

PS:里面有一些表和mapping方法可以去掉,对代码本身没有影响。 我们通过 CALL FUNCTION iv_function_name PARAMETER-TABLE ptab EXCEPTION-TABLE etab. 可以动态的对函数进行调用。

不过sap标准的json转换方法存在一定的bug,/ui2/cl_json=>generate转换json的时候,如果是金额类型的字段,并且不加””,会导致json序列化转换的时候将字段转换成f类型,f类型会导致金额在超过千万的时候会自动转换成科学计数法,导致数据异常。我们在处理的时候将/ui2/cl_json这个类copy了出来并在GENERATE_INT方法里做了修改,将下图为之的so_type_f改成了so_type_s,数据转换成string类型就不会产生科学计数法问题了。(这个增强位置可能不同版本的系统不一样,需要找一下具体的位置) 在这里插入图片描述 同时在程序里还支持了动态传入的JSON字符和SAP系统字段不一样时的mapping,通过调用json_mapping对字段进行处理即可。

METHOD json_mapping. SELECT fnam, " 函数名 direction, " 传输方向 field_sap, " sap字段名 field_other " 其他字段名 FROM zepict009 INTO TABLE @DATA(lt_mapping) WHERE fnam = @iv_function_name. CHECK lt_mapping IS NOT INITIAL. SORT lt_mapping BY field_sap. LOOP AT lt_mapping INTO DATA(ls_mapping). CASE ls_mapping-direction. " 判断接口传入方向 WHEN 'I'. INSERT VALUE #( abap = ls_mapping-field_sap json = ls_mapping-field_other ) INTO TABLE name_mappings_i. WHEN 'O'. INSERT VALUE #( abap = ls_mapping-field_sap json = ls_mapping-field_other ) INTO TABLE name_mappings_o. WHEN 'X'. INSERT VALUE #( abap = ls_mapping-field_sap json = ls_mapping-field_other ) INTO TABLE name_mappings_x. WHEN OTHERS. INSERT VALUE #( abap = ls_mapping-field_sap json = ls_mapping-field_other ) INTO TABLE name_mappings_i. INSERT VALUE #( abap = ls_mapping-field_sap json = ls_mapping-field_other ) INTO TABLE name_mappings_o. ENDCASE. ENDLOOP. ENDMETHOD.


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3